﻿package kliment.display {
	import flash.display.DisplayObject;
	import flash.display.InteractiveObject;
	import flash.display.MovieClip;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.EventPhase;
	import flash.events.MouseEvent;
	import flash.utils.clearInterval;
	import flash.utils.setInterval;
	import kliment.events.MovieClipButtonEvent;
	import kliment.utils._Sprite;
	
	/**
     * Dispatched when mouse roll over.
     */
    [Event(name = 'roll_over', type = 'kliment.events.MovieClipButtonEvent')]
	/**
     * Dispatched when mouse roll out.
     */
    [Event(name = 'roll_out', type = 'kliment.events.MovieClipButtonEvent')]
	/**
     * Dispatched when mouse release.
     */
    [Event(name = 'release', type = 'kliment.events.MovieClipButtonEvent')]
	/**
     * Dispatched when mouse release outside.
     */
    [Event(name = 'release_outside', type = 'kliment.events.MovieClipButtonEvent')]
	/**
     * Dispatched when mouse double click.
     */
    [Event(name = 'double_click', type = 'kliment.events.MovieClipButtonEvent')]
	/**
     * Dispatched when mouse down/press.
     */
    [Event(name = 'mouse_down', type = 'kliment.events.MovieClipButtonEvent')]
	/**
     * Dispatched when mouse presing.
     */
    [Event(name = 'mouse_pressing', type = 'kliment.events.MovieClipButtonEvent')]
	/**
     * Dispatched when mouse move.
     */
    [Event(name = 'mouse_move', type = 'kliment.events.MovieClipButtonEvent')]
	/**
     * Dispatched when mouse up.
     */
    [Event(name = 'mouse_up', type = 'kliment.events.MovieClipButtonEvent')]
	/**
     * Dispatched when mouse wheel.
     */
    [Event(name = 'mouse_wheel', type = 'kliment.events.MovieClipButtonEvent')]
	
	/**
	 * ...
	 * @author	Kliment
	 * @version	1.3.18
	 */
	public class MovieClipButton extends MovieClip {
		protected var _hit_mc:Sprite;
		private var _intervalID:uint;
		private var _enable:Boolean = true;
		private var _isMouseDown:Boolean = false;
		private var _isFocus:Boolean = false;
		private var _repeatDalay:uint = 100;
		static private var _isLock:Boolean = false;
		static public var lockOtherByttons:Boolean = true;
		
		public function MovieClipButton() {
			super();
			
			try {
				_hit_mc = this['hit_mc'];
				hitArea = _hit_mc;
			} catch (e:Error) {  }
			
			mouseChildren = false;
			addEventListener(MouseEvent.ROLL_OVER, _privateMouseEventsHandler);
			gotoAndStop(1);
		}
		
		private function _privateMouseEventsHandler(event:MouseEvent):void {
			switch(event.type) {
				case MouseEvent.ROLL_OVER:
					_isFocus = true;
					if (!_isMouseDown && _enable && !_isLock) {
						addEventListener(MouseEvent.MOUSE_DOWN, _privateMouseEventsHandler);
						addEventListener(MouseEvent.ROLL_OUT, _privateMouseEventsHandler);
						if (hasEventListener(MovieClipButtonEvent.MOUSE_WHEEL)) 
							addEventListener(MouseEvent.MOUSE_WHEEL, _privateMouseEventsHandler);
						if (hasEventListener(MovieClipButtonEvent.MOUSE_MOVE)) 
							addEventListener(MouseEvent.MOUSE_MOVE, _privateMouseEventsHandler);
						if (doubleClickEnabled && hasEventListener(MovieClipButtonEvent.DOUBLE_CLICK)) 
							addEventListener(MouseEvent.DOUBLE_CLICK, _privateMouseEventsHandler);
						stage.addEventListener(MouseEvent.MOUSE_UP, _mouseUpStageHandler);
						stage.addEventListener(MouseEvent.MOUSE_UP, _mouseUpStageHandler, true);
						addEventListener(MouseEvent.MOUSE_UP, _privateMouseEventsHandler);
						dispatchEvent(MovieClipButtonEvent.convert(event, MovieClipButtonEvent.ROLL_OVER, this));
					}
				break;
				
				case MouseEvent.MOUSE_WHEEL:
					dispatchEvent(MovieClipButtonEvent.convert(event, MovieClipButtonEvent.MOUSE_WHEEL, this));
				break;
				
				case MouseEvent.MOUSE_DOWN:
					_isMouseDown = true;
					_isLock = (lockOtherByttons)?true:false;
					clearInterval(_intervalID);
					if (hasEventListener(MovieClipButtonEvent.MOUSE_PRESSING))
						_intervalID = setInterval(_onMouseDown, _repeatDalay * 2);
					dispatchEvent(MovieClipButtonEvent.convert(event, MovieClipButtonEvent.MOUSE_DOWN, this));
				break;
				
				case MouseEvent.MOUSE_MOVE:
					if (_isFocus)
						dispatchEvent(MovieClipButtonEvent.convert(event, MovieClipButtonEvent.MOUSE_MOVE, this));
				break;
				
				case MouseEvent.MOUSE_UP:
					_isMouseDown = false;
					dispatchEvent(MovieClipButtonEvent.convert(event, MovieClipButtonEvent.MOUSE_UP, this));
				break;
				
				case MouseEvent.DOUBLE_CLICK:
					dispatchEvent(MovieClipButtonEvent.convert(event, MovieClipButtonEvent.DOUBLE_CLICK, this));
				break;
				
				case MouseEvent.ROLL_OUT:
					_isFocus = false;
					if (!_isMouseDown) {
						removeEventListener(MouseEvent.MOUSE_WHEEL, _privateMouseEventsHandler);
						removeEventListener(MouseEvent.MOUSE_DOWN, _privateMouseEventsHandler);
						removeEventListener(MouseEvent.MOUSE_MOVE, _privateMouseEventsHandler);
						removeEventListener(MouseEvent.ROLL_OUT, _privateMouseEventsHandler);
						if (stage) {
							stage.removeEventListener(MouseEvent.MOUSE_UP, _mouseUpStageHandler);
							stage.removeEventListener(MouseEvent.MOUSE_UP, _mouseUpStageHandler, true);
						}
						if (hasEventListener(MouseEvent.DOUBLE_CLICK))
							addEventListener(MouseEvent.DOUBLE_CLICK, _privateMouseEventsHandler);
						
						dispatchEvent(MovieClipButtonEvent.convert(event, MovieClipButtonEvent.ROLL_OUT, this));
					}
				break;
			}
		}
		
		public function stopPressing():void {
			clearInterval(_intervalID);
		}
		
		private function _onMouseDown():void {
			clearInterval(_intervalID);
			_intervalID = setInterval(_onMousePressing, _repeatDalay);
		}
		
		private function _onMousePressing():void {
			dispatchEvent(new MovieClipButtonEvent(MovieClipButtonEvent.MOUSE_PRESSING));
		}
		
		private function _mouseUpStageHandler(event:MouseEvent):void {
			if (event.eventPhase == EventPhase.BUBBLING_PHASE) 
				return;
			if (_isMouseDown) { 
				_isMouseDown = false;
				if (_isFocus) 
					dispatchEvent(MovieClipButtonEvent.convert(event, MovieClipButtonEvent.RELEASE, this));
				else 
					dispatchEvent(MovieClipButtonEvent.convert(event, MovieClipButtonEvent.RELEASE_OUTSIDE, this));
				stopPressing();
				_isLock = false;
			}
		}
		
		override public function toString():String {
			return '[object MovieClipButton]';
		}
		
		public function get enable():Boolean { return _enable; }
		public function set enable(value:Boolean):void {
			_enable = value;
			buttonMode = _enable;
		}
		
		public function get repeatDalay():uint { return _repeatDalay; }
		public function set repeatDalay(value:uint):void {
			_repeatDalay = value;
		}
		
		public function remove():DisplayObject {
			removeEventListener(MouseEvent.ROLL_OVER, _privateMouseEventsHandler);
			return _Sprite.remove(this);
		}
	}

}